/*
 *   Copyright (c) 2010-2022, SIUFUNG
 */
package net.siufung.market.base.permit.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.model.VerifyRepeatDto;
import net.siufung.core.model.enums.DeletedEnum;
import net.siufung.core.model.enums.MethodEventEnum;
import net.siufung.core.page.PagerResult;
import net.siufung.core.result.Result;
import net.siufung.core.result.ResultFail;
import net.siufung.core.result.ResultOk;
import net.siufung.core.utils.CopyUtil;
import net.siufung.market.base.permit.controller.assembler.RoleAssembler;
import net.siufung.market.base.permit.controller.model.dto.RoleDto;
import net.siufung.market.base.permit.controller.model.dto.RolePermitCountDto;
import net.siufung.market.base.permit.controller.model.dto.RoleSaveDto;
import net.siufung.market.base.permit.controller.model.dto.RoleUpdateDto;
import net.siufung.market.base.permit.controller.model.dto.page.RolePageDto;
import net.siufung.market.base.permit.controller.model.vo.RoleVo;
import net.siufung.market.base.permit.controller.regulation.RoleCreateRegulation;
import net.siufung.market.base.permit.controller.regulation.RoleDeleteRegulation;
import net.siufung.market.base.permit.controller.regulation.RoleUpdateRegulation;
import net.siufung.market.base.permit.mapper.IRoleMapper;
import net.siufung.market.base.permit.mapper.IRolePermitMapper;
import net.siufung.market.base.permit.mapper.entity.Role;
import net.siufung.market.base.permit.service.IRoleService;
import net.siufung.market.base.permit.spi.IRoleUserCountSpi;
import net.siufung.market.base.permit.spi.dto.RoleUserCountDto;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Objects;

/**
 * 系统角色表 前端控制器
 *
 * @author 陈建峰
 * @since 2022-07-05 16:14:50
 */
@Api(tags = "角色管理")
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/sys/role")
public class RoleController {

    private final IRoleService roleService;
    private final IRoleMapper roleMapper;
    private final IRoleUserCountSpi roleUserCountSpi;
    private final IRolePermitMapper rolePermitMapper;

    /**
     * 通过主键获取 系统角色表
     * @param id 主键
     * @return Result<RoleVo>
     * */
    @ApiOperation(value = "通过Id获取系统角色表信息")
    @GetMapping(value = "/id/{id}")
    public Result<RoleVo> getById(
            @PathVariable("id") Integer id) {
        return Result.ok(
            RoleAssembler.from(roleMapper.selectById(id)));
    }

    /**
     * 获取 系统角色表列表
     * @param roleDto 属性
     * @return Result<List<RoleVo>>
     * */
    @ApiOperation(value = "获取系统角色表列表")
    @PostMapping(value = "/list")
    public Result<List<RoleVo>> list(
            @RequestBody RoleDto roleDto) {
        return Result.ok(
            RoleAssembler.fromList(roleMapper.selectList(Wrappers.query(roleDto.to()))));
    }

    /**
     * 获取 系统角色表分页
     * @param rolePageDto 属性
     * @return 查询分页结果
     * */
    @ApiOperation(value = "获取系统角色表分页")
    @PostMapping(value="/page")
    public Result<PagerResult<RoleVo>> getPage(
            @RequestBody RolePageDto rolePageDto) {
        rolePageDto.validated();
        IPage<Role> rolePage = roleMapper.selectPage(
                new Page<>(rolePageDto.getPageNo(), rolePageDto.getPageSize()),
                new LambdaQueryWrapper<Role>()
                        .orderByDesc(Role::getId)
                        .eq(!Strings.isNullOrEmpty(rolePageDto.getRoleCode()), Role::getRoleCode,
                                rolePageDto.getRoleCode())
                        .like(!Strings.isNullOrEmpty(rolePageDto.getRoleName()), Role::getRoleName,
                                rolePageDto.getRoleName()));
        PagerResult<RoleVo> roleVoPage = new PagerResult<>(
                rolePage.getCurrent(), rolePage.getSize(), rolePage.getTotal());
        List<RoleUserCountDto> userCountDtoList = Lists.newArrayList();
        List<RolePermitCountDto> rolePermitCountDtoList = Lists.newArrayList();
        List<Role> roleList = rolePage.getRecords();
        if(!CollectionUtils.isEmpty(roleList)){
            Integer[] roleIdList = roleList.stream()
                    .map(Role::getId).toArray(Integer[]::new);
            if(Objects.nonNull(roleUserCountSpi)){
                userCountDtoList = roleUserCountSpi.getRoleUserCountList(roleIdList);
            }
            rolePermitCountDtoList = rolePermitMapper.getRolePermitCountList(roleIdList);
        }
        roleVoPage.setRecords(
            RoleAssembler.fromList(rolePage.getRecords(), userCountDtoList, rolePermitCountDtoList));
        return Result.ok(roleVoPage);
    }

    /**
     * 通过主键删除 系统角色表 对象
     * @param id 主键
     * @return 删除结果
     * */
    @ApiOperation(value = "删除系统角色表对象")
    @PostMapping(value="/remove/{id}")
    public Result<Void> removeById(
        @PathVariable("id") Integer id) {
        RoleDeleteRegulation roleDeleteRegulation = new RoleDeleteRegulation(roleUserCountSpi);
        roleDeleteRegulation.isSatisfiedBy(id);
        if(roleService.removeById(id)){
            return Result.ok(ResultOk.REMOVE);
        }
        return Result.fail(ResultFail.DATA_REMOVE_ERROR);
    }

    /**
     * 创建 系统角色表
     * @param roleSaveDto 对象属性
     * @return 创建结果
     * */
    @ApiOperation(value = "创建 系统角色表")
    @PostMapping(value="/create")
    public Result<Void> create(
            @RequestBody RoleSaveDto roleSaveDto) {
        roleSaveDto.validated();
        RoleCreateRegulation roleCreateRegulation = new RoleCreateRegulation(roleMapper);
        roleCreateRegulation.isSatisfiedBy(roleSaveDto);
        if(roleService.save(roleSaveDto.to())){
            return Result.ok(ResultOk.ADD);
        }
        return Result.fail(ResultFail.DATA_ADD_ERROR);
    }

    /**
     * 更新 系统角色表
     * @param roleUpdateDto 对象属性
     * @return Result<Void>
     * */
    @ApiOperation(value = "更新 系统角色表 信息")
    @PostMapping(value="/update")
    public Result<Void> update(
            @RequestBody RoleUpdateDto roleUpdateDto) {
        roleUpdateDto.validated();
        RoleUpdateRegulation roleUpdateRegulation = new RoleUpdateRegulation(roleMapper);
        roleUpdateRegulation.isSatisfiedBy(roleUpdateDto);
        Role roleOf = roleService.getById(roleUpdateDto.getId());
        CopyUtil.copyPropertiesIgnoreNull(roleUpdateDto.to(), roleOf);
        if(roleService.updateById(roleOf)){
            return Result.ok(ResultOk.UPDATE);
        }
        return Result.fail(ResultFail.DATA_UPDATE_ERROR);
    }

    /**
     * 更新 系统角色表 状态
     * @param id 主键
     * @param deleted 数据状态
     * @return Result<Void>
     * */
    @ApiOperation(value = "更新 系统角色表 状态")
    @PostMapping(value="/status/{id}/{deleted}")
    public Result<Void> updateStatusById(
            @PathVariable("id") Integer id,
            @PathVariable("deleted") boolean deleted) {
        if(roleService.updateStatusById(id, DeletedEnum.get(deleted))){
            return Result.ok(ResultOk.STATUS);
        }
        return Result.fail(ResultFail.DATA_UPDATE_ERROR);
    }

    /**
     * 判断名称是否重复
     * @param roleName 名称
     * @param event 事件
     * @param id Key
     * @return Result<Boolean>
     */
    @ApiOperation(value = "判断名称是否重复", notes = "")
    @PostMapping(value="/checkNameRepeat")
    public Result<Boolean> checkNameRepeat(
            @RequestParam("roleName") String roleName,
            @RequestParam(value = "event") String event,
            @RequestParam(value = "id", required = false) Integer id) {
        VerifyRepeatDto<Integer> verifyRepeatDto = new VerifyRepeatDto<>();
        verifyRepeatDto.setVerifyKeyValue(roleName);
        verifyRepeatDto.setMethodEventEnum(MethodEventEnum.get(event));
        verifyRepeatDto.setPk(id);
        boolean notRepeat = roleMapper.checkRoleNameNotRepeat(verifyRepeatDto);
        if(notRepeat){
            return Result.ok("角色名称可用!");
        }
        return Result.fail(ResultFail.PARAM_REPEAT_ERROR);
    }

    /**
     * 判断编码是否重复
     * @param roleCode 名称
     * @param event 事件
     * @param id Key
     * @return Result<Boolean>
     */
    @ApiOperation(value = "判断编码是否重复", notes = "")
    @PostMapping(value="/checkCodeRepeat")
    public Result<Boolean> checkCodeRepeat(
            @RequestParam("roleCode") String roleCode,
            @RequestParam(value = "event") String event,
            @RequestParam(value = "id", required = false) Integer id) {
        VerifyRepeatDto<Integer> verifyRepeatDto = new VerifyRepeatDto<>();
        verifyRepeatDto.setVerifyKeyValue(roleCode);
        verifyRepeatDto.setMethodEventEnum(MethodEventEnum.get(event));
        verifyRepeatDto.setPk(id);
        boolean notRepeat = roleMapper.checkRoleCodeNotRepeat(verifyRepeatDto);
        if(notRepeat){
            return Result.ok("角色编码可用!");
        }
        return Result.fail(ResultFail.PARAM_REPEAT_ERROR);

    }

}